
//mpu6050和dmp初始化
void mpu_init_dmp(void)
{
    // 1. 初始化MPU6050硬件
    mpu_init();
    // 2. 配置传感器工作模式
    mpu_set_sensors(INV_XYZ_GYRO | INV_XYZ_ACCEL);   
    // 3. 配置FIFO
    mpu_configure_fifo(INV_XYZ_GYRO | INV_XYZ_ACCEL);    
    // 4. 设置采样率
    mpu_set_sample_rate(DEFAULT_MPU_HZ);  // 100Hz    
    // 5. 加载DMP固件
    dmp_load_motion_driver_firmware();   
    // 6. 设置传感器方向
    dmp_set_orientation(inv_orientation_matrix_to_scalar(gyro_orientation));    
    // 7. 启用DMP功能
    hal.dmp_features = DMP_FEATURE_6X_LP_QUAT | DMP_FEATURE_TAP |
                       DMP_FEATURE_ANDROID_ORIENT | DMP_FEATURE_SEND_RAW_ACCEL | 
                       DMP_FEATURE_SEND_CAL_GYRO | DMP_FEATURE_GYRO_CAL;
    dmp_enable_feature(hal.dmp_features);    
    // 8. 设置FIFO速率并启动DMP
    dmp_set_fifo_rate(DEFAULT_MPU_HZ);
    mpu_set_dmp_state(1);
}
/*在DMP固件内部：
数据采集：以200Hz频率持续采集加速度数据
信号处理：
去除重力分量
数字滤波去除噪声
计算合加速度：accel_total = √(accel_x² + accel_y² + accel_z²)
步态识别：
检测加速度波形的周期性峰值
通过阈值判断识别有效步数
过滤非步行运动（如抖动）
计数存储：将步数存储在DMP内存的特定地址
*/
//应用程序读取步数
static void mpu_get_dmp_data(void)
{ 
    // 读取步数数据
    unsigned long pSportStep = 0;
    unsigned long pSportTime = 0;
    
    // 从DMP内存读取步数
    dmp_get_pedometer_step_count(&pSportStep);
    
    // 从DMP内存读取运动时间
    dmp_get_pedometer_walk_time(&pSportTime);
    
    // 保存到全局变量
    gSportStep = pSportStep;
    gSportTime = pSportTime;
}
//dmp底层驱动函数
//实际的步数读取函数
int dmp_get_pedometer_step_count(unsigned long *count)
{
    unsigned char tmp[4];
    
    // 从DMP内存地址读取4字节步数数据
    if (mpu_read_mem(D_PEDSTD_STEPCTR, 4, tmp))
        return -1;

    // 将4个字节组合成32位步数值
    count[0] = ((unsigned long)tmp[0] << 24) | 
               ((unsigned long)tmp[1] << 16) |
               ((unsigned long)tmp[2] << 8) | 
               tmp[3];
    return 0;
}
//温湿度读取
//在系统初始化时调用
void BSP_SHT20_Init(void)
{
    // 1. 初始化I2C总线
    MX_I2C1_Init();
    
    // 2. 发送软复位命令
    uint8_t reset_cmd = 0xFE;
    HAL_I2C_Master_Transmit(&hi2c1, SHT20_I2C_ADDR, &reset_cmd, 1, 100);
    
    // 3. 等待复位完成
    HAL_Delay(15);
}
//温度测量过程
float SHT20_ReadTemperature(void)
{
    uint8_t cmd = 0xF3;  // 温度测量命令（无保持主模式）
    uint8_t data[3];
    uint16_t raw_value;
    float temperature;
    
    // 1. 发送温度测量命令
    HAL_I2C_Master_Transmit(&hi2c1, SHT20_I2C_ADDR, &cmd, 1, 100);
    
    // 2. 等待测量完成（典型时间85ms）
    HAL_Delay(100);
    
    // 3. 读取3字节数据
    //    data[0]: 高8位
    //    data[1]: 低8位  
    //    data[2]: CRC校验（可选）
    HAL_I2C_Master_Receive(&hi2c1, SHT20_I2C_ADDR, data, 3, 100);
    
    // 4. 组合原始数据
    raw_value = (data[0] << 8) | data[1];
    
    // 5. 转换为实际温度值
    //    公式: T = -46.85 + 175.72 * (raw_value / 65536)
    temperature = -46.85 + 175.72 * (raw_value / 65536.0);
    
    return temperature;
}
//湿度测量过程
float SHT20_ReadHumidity(void)
{
    uint8_t cmd = 0xF5;  // 湿度测量命令（无保持主模式）
    uint8_t data[3];
    uint16_t raw_value;
    float humidity;
    
    // 1. 发送湿度测量命令
    HAL_I2C_Master_Transmit(&hi2c1, SHT20_I2C_ADDR, &cmd, 1, 100);
    
    // 2. 等待测量完成（典型时间29ms）
    HAL_Delay(50);
    
    // 3. 读取3字节数据
    HAL_I2C_Master_Receive(&hi2c1, SHT20_I2C_ADDR, data, 3, 100);
    
    // 4. 组合原始数据
    raw_value = (data[0] << 8) | data[1];
    
    // 5. 转换为实际湿度值
    //    公式: RH = -6.0 + 125.0 * (raw_value / 65536)
    humidity = -6.0 + 125.0 * (raw_value / 65536.0);
    
    // 6. 限制湿度范围在0-100%
    if (humidity > 100.0) humidity = 100.0;
    if (humidity < 0.0) humidity = 0.0;
    
    return humidity;
}